﻿using System;
using System.Collections.Generic;
using System.Text;
using SimioAPI;
using SimioAPI.Extensions;

namespace WLC
{
    public class WLCUpdateCriticalRatioStepDefinition : IStepDefinition
    {
        #region IStepDefinition Members

        /// <summary>
        /// Property returning the full name for this type of step. The name should contain no spaces. 
        /// </summary>
        public string Name
        {
            get { return "UpdateCriticalRatio"; }
        }

        /// <summary>
        /// Property returning a short description of what the step does.  
        /// </summary>
        public string Description
        {
            get { return "Updates the critical ration for an order."; }
        }

        /// <summary>
        /// Property returning an icon to display for the step in the UI. 
        /// </summary>
        public System.Drawing.Image Icon
        {
            get { return null; }
        }

        /// <summary>
        /// Property returning a unique static GUID for the step.  
        /// </summary>
        public Guid UniqueID
        {
            get { return MY_ID; }
        }
        static readonly Guid MY_ID = new Guid("{5210B5DA-4564-11DF-9314-487055D89593}");

        /// <summary>
        /// Property returning the number of exits out of the step. Can return either 1 or 2. 
        /// </summary>
        public int NumberOfExits
        {
            get { return 1; }
        }

        /// <summary>
        /// Method called that defines the property schema for the step.
        /// </summary>
        public void DefineSchema(IPropertyDefinitions schema)
        {

            IPropertyDefinition pd;
            pd = schema.AddStateProperty("CriticalRatioState");
            pd.DisplayName = "CriticalRatioState";
            pd.Description = "The order's state where the critical ration is stored.";
            pd.Required = true;

            IPropertyDefinition pd2;
            pd2 = schema.AddElementProperty("OrderSequence", WLCSequenceElementDefinition.ID);
            pd2.DisplayName = "OrderSequence";
            pd2.Description = "The order's sequence.";
            pd2.Required = true;
        }

        /// <summary>
        /// Method called to create a new instance of this step type to place in a process. 
        /// Returns an instance of the class implementing the IStep interface.
        /// </summary>
        public IStep CreateStep(IPropertyReaders properties)
        {
            return new WLCUpdateCriticalRatioStep(properties);
        }

        #endregion
    }

    class WLCUpdateCriticalRatioStep : IStep
    {
        IPropertyReaders _properties;
        IStateProperty _criticalRatioStateProp;
        IElementProperty _sequenceProp;

        public WLCUpdateCriticalRatioStep(IPropertyReaders properties)
        {
            _properties = properties;
            _criticalRatioStateProp = (IStateProperty)properties.GetProperty("CriticalRatioState");
            _sequenceProp = (IElementProperty)properties.GetProperty("OrderSequence");

        }

        #region IStep Members

        /// <summary>
        /// Method called when a process token executes the step.
        /// </summary>
        public ExitType Execute(IStepExecutionContext context)
        {

            WLCSequenceElement sequence = (WLCSequenceElement)_sequenceProp.GetElement(context);
            IState criticalRationState = _criticalRatioStateProp.GetState(context);

            double sumProcessingTime = 0;
            
            int orderSize = (int)context.AssociatedObject.States["OrderSize"].StateValue;
            double dueDate = context.AssociatedObject.States["OrderDueDate"].StateValue;
            double timeNow = context.Calendar.TimeNow;


            for (int i = 0; i < sequence.GetNumberOfSteps(); i++)
            {
                sumProcessingTime += (sequence.GetSequenceProcessingTime(i) * orderSize);
            }

            criticalRationState.StateValue = sumProcessingTime / (dueDate - timeNow);
            context.ExecutionInformation.TraceInformation("CRITICAL RATIO updated to " + criticalRationState.StateValue.ToString());


            return ExitType.FirstExit;
        }

        #endregion
    }
}
